﻿using System;
using System.Data;

namespace mklib.json
{
	internal static class DataToJson
	{
		private static IJsonValue Convert(DataRow row, int depth)
		{
			JsonValueObject obj = new JsonValueObject (depth);
			foreach (DataColumn dc in row.Table.Columns) {
				obj [dc.ColumnName] = JsonHelper.GetJSValue (row [dc], depth + 1);
			}
			return new JsonValue (obj, JsonValueType.Object, null, depth);
		}

		private static IJsonValue Convert(DataTable dt, int depth)
		{
			if (dt.Rows.Count == 1) {
				return Convert (dt.Rows [0], depth);
			} else if (dt.Rows.Count < 1) {
				return new JsonValueArray (depth);
			}

			JsonValueArray arr = new JsonValueArray (depth);
			foreach (DataRow row in dt.Rows) {
				arr.Add (Convert (row, depth + 1));
			}
			return new JsonValue (arr, JsonValueType.Array, null, depth);
		}

		private static IJsonValue Convert(DataTable dt, int depth, bool compress)
		{
			if (!compress)
				return Convert (dt, depth);
			JsonValueArray arr = new JsonValueArray (depth);
			foreach (DataRow row in dt.Rows) {
				foreach (DataColumn dc in dt.Columns) {
					arr.Add (JsonHelper.GetJSValue (row [dc], depth + 1));
				}
			}
			return new JsonValue (arr, JsonValueType.Array, null, depth);
		}

		private static IJsonValue Convert(DataTable dt)
		{
			return Convert (dt, 0);
		}

		private static IJsonValue Schema(DataTable dt, int depth)
		{
			JsonValueObject obj = new JsonValueObject (depth);
			foreach (DataColumn dc in dt.Columns) {
				obj [dc.ColumnName] = JsonHelper.GetJSValue (dc.DataType.FullName, depth + 1);
			}
			return new JsonValue (obj, JsonValueType.Object, null, depth);
		}

		private static IJsonValue Schema(DataTable dt, int depth, bool compress)
		{
			if (!compress)
				return Schema (dt, depth);
			JsonValueArray arr = new JsonValueArray (depth);
			foreach (DataColumn dc in dt.Columns) {
				arr.Add(JsonHelper.GetJSValue (dc.ColumnName, depth + 1));
			}
			return new JsonValue (arr, JsonValueType.Array, null, depth);
		}

		internal static IJsonValue Convert(DataTable dt, int depth, JsonDataParseType type)
		{
			bool compress = type.HasFlag (JsonDataParseType.Compress);
			bool useSchema = type.HasFlag (JsonDataParseType.Schema);
			bool useData = type.HasFlag (JsonDataParseType.Data);

			if (useSchema && useData) {
				if (compress) {
					JsonValueArray arr = new JsonValueArray (depth);
					arr.Add (Schema (dt, depth + 1, true));
					arr.Add (Convert (dt, depth + 1, true));
					return new JsonValue (arr, JsonValueType.Array, null, depth);
				} else {
					JsonValueObject obj = new JsonValueObject (depth);
					obj ["schema"] = Schema (dt, depth + 1);
					obj ["data"] = Convert (dt, depth + 1);
					return new JsonValue (obj, JsonValueType.Object, null, depth);
				}
			} else if (useSchema) {
				return Schema (dt, depth, compress);
			} else if (useData) {
				return Convert (dt, depth, compress);
			} else {
				return new JsonValue (null, JsonValueType.Null, null, depth);
			}
		}
	}
}

